Skip to content

Fix intermediate pages not receiving query parameters in multi-page Shell navigation#35432

Merged
kubaflo merged 4 commits into
inflight/currentfrom
mattleibow/fix-intermediate-page-params
May 21, 2026
Merged

Fix intermediate pages not receiving query parameters in multi-page Shell navigation#35432
kubaflo merged 4 commits into
inflight/currentfrom
mattleibow/fix-intermediate-page-params

Conversation

@mattleibow
Copy link
Copy Markdown
Member

@mattleibow mattleibow commented May 13, 2026

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description

Fixes #35107

When Shell.GoToAsync pushes multiple pages in a single call (e.g., "product/review"), only the last page receives query parameters. All intermediate pages silently receive nothing — no IQueryAttributable.ApplyQueryAttributes call, no [QueryProperty] values set, no BindingContext propagation.

Root Cause

ShellNavigationManager.ApplyQueryAttributes has two branches for delivering parameters:

  1. baseShellItem is ShellContent — applies params via the ShellContent instance method
  2. isLastItem — applies params by setting the QueryAttributesProperty attached property

For intermediate pages (not last in the stack), the method tries to find a BaseShellItem parent:

if (!(element is BaseShellItem baseShellItem))
    baseShellItem = element?.Parent as BaseShellItem;

But intermediate pages were just created by ShellSection.GetOrCreateFromRoute and have not been added to the visual tree yet. Their Parent is null, so baseShellItem is null. Since the page is not a ShellContent and is not the last item, neither branch runs and the parameters are silently dropped.

The Fix

Added a third branch after the existing two:

else if (element is Page)
{
    var mergedData = MergeData(element, filteredQuery, isPopping);
    if (mergedData.Count > 0 || !isPopping)
    {
        element.SetValue(ShellContent.QueryAttributesProperty, mergedData);
    }
}

This sets the QueryAttributesProperty attached property directly on the page. The existing property-changed handler (ShellContent.OnQueryAttributesPropertyChanged) already handles:

  • IQueryAttributable interface dispatch
  • BindingContext propagation (if BindingContext differs from the page)
  • [QueryProperty] attribute reflection
  • ShellNavigationQueryParameters read-only wrapping

No logic was duplicated — the fix reuses the same infrastructure that already works for the last page and ShellContent cases.

How Parameter Scoping Works

Shell already has a prefix-based scoping mechanism for targeting specific pages in a multi-page navigation. For a route like "product/review":

  • ?product.sku=seed-tomato → delivered to the page with route "product" as sku=seed-tomato
  • ?stars=5 → delivered to the last page ("review") as stars=5
  • ?product.name=Widget&name=Alice"product" gets name=Widget, "review" gets name=Alice (no cross-contamination)

This prefix mechanism (ShellRouteParameters constructor with prefix filtering) was already implemented and correct — it just could not deliver because of the null-parent bug.

Testing

Unit tests (ShellParameterPassingTests.cs — 6 new tests):

  • Intermediate page receives prefixed params via IQueryAttributable
  • Intermediate page receives prefixed params via [QueryProperty]
  • Last page still receives unprefixed params (regression)
  • Multiple intermediate pages each receive their own prefixed params (3-page deep)
  • Overlapping param names deliver correct distinct values to each page
  • Intermediate page does NOT receive unprefixed params meant for the last page

UI tests (ShellNavigationFeatureTests.cs — 2 new tests):

  • Multi-page navigation delivers prefixed params to intermediate and unprefixed to last; verifies intermediate does not leak unprefixed params
  • Overlapping name key scoped correctly — intermediate and detail each see only their own value

…hell navigation

When Shell.GoToAsync pushes multiple pages (e.g. 'product/review'), only the
last page received query parameters. Intermediate pages silently got nothing
because their Parent is null (not yet in visual tree), causing baseShellItem
to be null. Neither the ShellContent branch nor the isLastItem branch would
run, so parameters were silently dropped.

Added a third branch in ApplyQueryAttributes for the case where the element
is a Page but baseShellItem is null. It sets the QueryAttributesProperty with
prefix-filtered parameters, which triggers the existing property-changed
handler to apply IQueryAttributable, BindingContext propagation, and
QueryProperty attributes.

Fixes #35107

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 13, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35432

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35432"

Add UI tests (Order 148-149) in ShellNavigationFeatureTests to verify
multi-page GoToAsync delivers prefixed params to intermediate pages and
unprefixed params to the last page, including overlapping param name
scoping.

Enhance QueryIntermediatePage to implement IQueryAttributable and display
received params. Add multi-page prefixed navigation button to
QuerySenderPage.

Add unit tests for overlapping param names and verifying intermediate
pages do not receive unprefixed params meant for the last page.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Shell multi-page navigation so intermediate pages can receive route-prefixed query parameters when GoToAsync pushes multiple pages in one call.

Changes:

  • Applies query attributes directly to intermediate Page instances that are not yet parented in the Shell visual tree.
  • Adds unit coverage for prefixed intermediate parameters, overlapping keys, and last-page parameter behavior.
  • Adds HostApp/UI test support for multi-page prefixed query navigation scenarios.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/Controls/src/Core/Shell/ShellNavigationManager.cs Adds direct query application for intermediate pages and minor cleanup.
src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs Adds Shell parameter passing regression tests for intermediate pages.
src/Controls/tests/TestCases.HostApp/FeatureMatrix/Shell/ShellNavigation/ShellNavigationControlPage.xaml.cs Extends the Shell navigation feature page with a multi-page prefixed query test flow.
src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs Adds Appium feature tests for intermediate/last-page scoped query parameters.

// which triggers OnQueryAttributesPropertyChanged to handle IQueryAttributable,
// BindingContext propagation, and [QueryProperty] attributes.
var mergedData = MergeData(element, filteredQuery, isPopping);
if (mergedData.Count > 0 || !isPopping)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 95e0ab7. Added the ShellContent-style guard:

if (filteredQuery.Count == 0 && !element.IsSet(ShellContent.QueryAttributesProperty))
    return;

This skips empty queries on fresh intermediate pages. For pages that previously had params set (re-navigation), an empty query still propagates to allow clearing.

Added test IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery to verify.

Comment on lines +341 to +344
var mergedData = MergeData(element, filteredQuery, isPopping);
if (mergedData.Count > 0 || !isPopping)
{
element.SetValue(ShellContent.QueryAttributesProperty, mergedData);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — but this is a pre-existing issue in the ShellRouteParameters(query, prefix) constructor (line 55-56 of ShellRouteParameters.cs). It copies _shellNavigationQueryParameters verbatim for ALL prefix-filtered queries, including those used in the ShellContent branch at line 311. The intermediate page branch inherits the same behavior.

Fixing this would require changing the shared constructor, which would also affect the ShellContent path. I think that warrants a separate issue/PR rather than mixing it into this bug fix.

@PureWeen
Copy link
Copy Markdown
Member

/review

@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented May 13, 2026

/review -b feature/regression-check

Copy link
Copy Markdown
Member

@PureWeen PureWeen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-Model Adversarial Code Review + MAUI Expert Review

Methodology: 3 independent reviewers (different models) with adversarial consensus, plus MAUI-specific expert dimension review. Disputed findings went through a follow-up round where the other reviewers weighed in.

✅ Verdict: LGTM (high confidence)

The fix is correct, minimal, and well-tested. The else if (element is Page) branch correctly delivers prefix-filtered query params to intermediate pages by reusing existing QueryAttributesProperty infrastructure. No correctness, security, or regression concerns survived cross-validation.

Confirmed safe:

  • No double-application risk (branch ordering prevents it)
  • SetValue is safe before page joins visual tree
  • Correctly uses filteredQuery (not full query) for intermediate pages
  • All shared code — no platform-specific concerns
  • No security, threading, or resource leak issues

Additional observations (not inline)

💡 Last page receives ALL params including prefixed keys for other pages — This is pre-existing behavior in Branch 2 (isLastItem uses full query, not filteredQuery). None of the new tests document this asymmetry. Consider adding an explicit assertion if this is intentional contract. (2/3 reviewers)

💡 ShellNavigationQueryParameters bypasses prefix filtering — The prefix constructor in ShellRouteParameters.cs (line 55-56) correctly filters string keys by prefix but copies _shellNavigationQueryParameters wholesale. Pre-existing issue from PR #15585, not introduced here. Worth tracking as a separate issue. (3/3 reviewers, all confirmed pre-existing)

💡 Whitespace reformatting mixed with functional changes in ShellNavigationFeatureTests.cs — space-to-tab fixes on existing code mixed with new test additions. Harmless but adds diff noise.

Comment thread src/Controls/src/Core/Shell/ShellNavigationManager.cs Outdated
Comment thread src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs
- Add ShellContent-style guard: skip empty filteredQuery on intermediate
  pages if QueryAttributesProperty was never previously set. Prevents
  spurious empty ApplyQueryAttributes calls during multi-page navigation
  when no prefixed params target the intermediate page.

- Fix misleading comment: remove 'Parent is null' claim since the branch
  also fires for in-stack pages from PrepareCurrentStackForBeingReplaced.

- Add test: IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery
  verifies the empty-query guard works correctly.

- Add test: IntermediatePageReceivesParamsOnReNavigation verifies params
  are delivered on subsequent navigations to the same route.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JanKrivanek
Copy link
Copy Markdown
Member

/review -b feature/regression-check

@JanKrivanek
Copy link
Copy Markdown
Member

/azp-run maui-pr-devicetests

@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented May 19, 2026

/review -b feature/regression-check

@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented May 19, 2026

/review -b feature/regression-check -p android

2 similar comments
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented May 19, 2026

/review -b feature/regression-check -p android

@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented May 19, 2026

/review -b feature/regression-check -p android

JanKrivanek added a commit that referenced this pull request May 20, 2026
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Problem

The `/review` slash command in `.github/workflows/review-trigger.yml` is
silently skipped when the comment body has any **leading whitespace**
before `/review`.

Concrete example:
- Comment posted on #35432:
#35432 (comment)
- Body (raw bytes): `' /review -b feature/regression-check'` — note the
leading space (`0x20`).
- Result: workflow run
https://github.com/dotnet/maui/actions/runs/25824871590 → **skipped**.

### Root cause

The job-level guard was:

```yaml
if: >-
  github.event_name == 'workflow_dispatch' ||
  (github.event.issue.pull_request &&
   (github.event.comment.body == '/review' ||
    startsWith(github.event.comment.body, '/review ')))
```

`startsWith(' /review ...', '/review ')` returns `false`, so the job is
skipped. GitHub expression syntax has no `trim` or regex, so we can't
fix this purely at the expression level. The `Parse parameters` step had
the same blind spot — `sed -n 's|^/review[[:space:]]*||p'` produces
empty `ARGS` if the body doesn't start with `/review`.

### Fix

1. **New tiny `match` pre-filter job** that uses a bash regex
(`^[[:space:]]*/review([[:space:]]|$)`) to decide whether the comment is
a `/review` command. It allows arbitrary leading whitespace (spaces,
tabs, newlines) but still requires `/review` to be a standalone token
(won't match `/reviewfoo` or comments that merely mention `/review`
mid-sentence).
2. **`trigger-review` now `needs: match`** and gates on its output,
keeping the rest of the job structure intact.
3. **Trim leading whitespace before `sed`** in `Parse parameters`, so
flag/positional parsing works on prefixed comments like ` /review -b
feature/foo`.

### Verification

Local check of the regex against representative inputs:

| Body                                | Should match | Matches |
|-------------------------------------|--------------|---------|
| `/review`                           | yes          | yes     |
| `/review android`                   | yes          | yes     |
| ` /review -b feature/regression-check` (the failing case) | yes | yes
|
| `\t/review`                         | yes          | yes     |
| `   /review -p ios`                 | yes          | yes     |
| `/reviewfoo`                        | no           | no      |
| `please /review this`               | no           | no      |
| `not a command`                     | no           | no      |

The full end-to-end behavior will be exercised by the next `/review`
invocation on a PR that targets this branch.
@dotnet dotnet deleted a comment from MauiBot May 21, 2026
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented May 21, 2026

/review -b feature/regression-check -p ios

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented May 21, 2026

🤖 AI Summary

👋 @mattleibow — new AI review results are available. Please review the latest session below.

📊 Review Session95e0ab7 · Address PR review: empty-query guard, fix comment, add tests · 2026-05-21 13:03 UTC
🚦 Gate — Test Before & After Fix

Gate Result: ❌ FAILED

Platform: IOS · Base: main · Merge base: 1eb20831

🩺 Regression in another test — at least one test goes FAIL→PASS (fix works there), but another test FAILs both with and without the fix. The fix breaks a pre-existing or sibling test.

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ ShellNavigationFeatureTests ShellNavigationFeatureTests ✅ FAIL — 579s ❌ FAIL — 367s
🧪 ShellParameterPassingTests ShellParameterPassingTests ✅ FAIL — 12s ✅ PASS — 9s
🔴 Without fix — 🖥️ ShellNavigationFeatureTests: FAIL ✅ · 579s

(truncated to last 15,000 chars)

igationSucceeds Start
  Passed RouteRegistration_UnregisterRoute_NavigationFails [1 s]
>>>>> 5/21/2026 4:35:11 AM RouteRegistration_ReRegisterRoute_NavigationSucceeds Stop
  Passed RouteRegistration_ReRegisterRoute_NavigationSucceeds [4 s]
>>>>> 5/21/2026 4:35:11 AM CancelNavigation_NavigationIsBlocked_StaysOnMain Start
>>>>> 5/21/2026 4:35:18 AM CancelNavigation_NavigationIsBlocked_StaysOnMain Stop
  Passed CancelNavigation_NavigationIsBlocked_StaysOnMain [7 s]
>>>>> 5/21/2026 4:35:18 AM DeferralNavigation_NavigationCompletes_AfterDelay Start
>>>>> 5/21/2026 4:35:28 AM DeferralNavigation_NavigationCompletes_AfterDelay Stop
  Passed DeferralNavigation_NavigationCompletes_AfterDelay [10 s]
>>>>> 5/21/2026 4:35:28 AM TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo Start
>>>>> 5/21/2026 4:35:31 AM TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo Stop
  Passed TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo [2 s]
>>>>> 5/21/2026 4:35:31 AM TabStack_OnPushAsync_SubPage1_TabStackCountIsThree Start
>>>>> 5/21/2026 4:35:33 AM TabStack_OnPushAsync_SubPage1_TabStackCountIsThree Stop
  Passed TabStack_OnPushAsync_SubPage1_TabStackCountIsThree [1 s]
>>>>> 5/21/2026 4:35:33 AM TabStack_OnPushAsync_SubPage2_TabStackCountIsFour Start
>>>>> 5/21/2026 4:35:34 AM TabStack_OnPushAsync_SubPage2_TabStackCountIsFour Stop
  Passed TabStack_OnPushAsync_SubPage2_TabStackCountIsFour [1 s]
>>>>> 5/21/2026 4:35:34 AM TabStack_OnPopAsync_SubPage2_TabStackCountIsThree Start
>>>>> 5/21/2026 4:35:36 AM TabStack_OnPopAsync_SubPage2_TabStackCountIsThree Stop
  Passed TabStack_OnPopAsync_SubPage2_TabStackCountIsThree [1 s]
>>>>> 5/21/2026 4:35:36 AM TabStack_OnPopToRootAsync_ReturnsToMainPage Start
>>>>> 5/21/2026 4:35:38 AM TabStack_OnPopToRootAsync_ReturnsToMainPage Stop
  Passed TabStack_OnPopToRootAsync_ReturnsToMainPage [1 s]
>>>>> 5/21/2026 4:35:38 AM TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage Start
>>>>> 5/21/2026 4:35:41 AM TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage Stop
  Passed TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage [3 s]
>>>>> 5/21/2026 4:35:41 AM TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo Start
>>>>> 5/21/2026 4:35:42 AM TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo Stop
>>>>> 5/21/2026 4:35:42 AM TabStack_OnRemovePage_NoOp_WhenNothingToRemove Start
  Passed TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo [1 s]
>>>>> 5/21/2026 4:35:43 AM TabStack_OnRemovePage_NoOp_WhenNothingToRemove Stop
>>>>> 5/21/2026 4:35:43 AM TabStack_GetNavigationStack_TabStackMatchesNavigationStack Start
  Passed TabStack_OnRemovePage_NoOp_WhenNothingToRemove [1 s]
>>>>> 5/21/2026 4:35:49 AM TabStack_GetNavigationStack_TabStackMatchesNavigationStack Stop
  Passed TabStack_GetNavigationStack_TabStackMatchesNavigationStack [6 s]
>>>>> 5/21/2026 4:35:49 AM NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage Start
>>>>> 5/21/2026 4:35:55 AM NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage Stop
  Passed NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage [5 s]
>>>>> 5/21/2026 4:35:55 AM NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped Start
>>>>> 5/21/2026 4:35:55 AM NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped Stop
>>>>> 5/21/2026 4:35:55 AM NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage Start
  Passed NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped [789 ms]
>>>>> 5/21/2026 4:35:57 AM NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage Stop
>>>>> 5/21/2026 4:35:57 AM NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage Start
  Passed NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage [2 s]
>>>>> 5/21/2026 4:35:58 AM NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage Stop
>>>>> 5/21/2026 4:35:58 AM NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged Start
  Passed NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage [717 ms]
>>>>> 5/21/2026 4:36:04 AM NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged Stop
  Passed NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged [5 s]
>>>>> 5/21/2026 4:36:04 AM NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain Start
>>>>> 5/21/2026 4:36:05 AM NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain Stop
>>>>> 5/21/2026 4:36:05 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged Start
  Passed NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain [715 ms]
>>>>> 5/21/2026 4:36:06 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged Stop
>>>>> 5/21/2026 4:36:06 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged Start
>>>>> 5/21/2026 4:36:06 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged Stop
>>>>> 5/21/2026 4:36:06 AM NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged Start
  Passed NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged [1 s]
  Passed NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged [444 ms]
>>>>> 5/21/2026 4:36:11 AM NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged Stop
  Passed NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged [4 s]
>>>>> 5/21/2026 4:36:11 AM NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 Start
>>>>> 5/21/2026 4:36:12 AM NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 Stop
  Passed NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 [1 s]
>>>>> 5/21/2026 4:36:12 AM NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged Start
>>>>> 5/21/2026 4:36:18 AM NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged Stop
  Passed NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged [5 s]
>>>>> 5/21/2026 4:36:18 AM NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA Start
>>>>> 5/21/2026 4:36:19 AM NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA Stop
  Passed NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA [1 s]
>>>>> 5/21/2026 4:36:19 AM NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot Start
>>>>> 5/21/2026 4:36:24 AM NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot Stop
  Passed NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot [5 s]
>>>>> 5/21/2026 4:36:24 AM NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot Start
>>>>> 5/21/2026 4:36:25 AM NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot Stop
>>>>> 5/21/2026 4:36:25 AM PassData_StringQueryParam_ReceivedByIQueryAttributable Start
  Passed NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot [464 ms]
>>>>> 5/21/2026 4:36:33 AM PassData_StringQueryParam_ReceivedByIQueryAttributable Stop
  Passed PassData_StringQueryParam_ReceivedByIQueryAttributable [7 s]
>>>>> 5/21/2026 4:36:33 AM PassData_DictionaryParam_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:36:38 AM PassData_DictionaryParam_ReceivedByIQueryAttributable Stop
  Passed PassData_DictionaryParam_ReceivedByIQueryAttributable [5 s]
>>>>> 5/21/2026 4:36:38 AM PassData_SingleUseParams_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:36:43 AM PassData_SingleUseParams_ReceivedByIQueryAttributable Stop
  Passed PassData_SingleUseParams_ReceivedByIQueryAttributable [5 s]
>>>>> 5/21/2026 4:36:43 AM PassData_StringQueryParam_BothLabelsReceiveSameValue Start
>>>>> 5/21/2026 4:36:49 AM PassData_StringQueryParam_BothLabelsReceiveSameValue Stop
  Passed PassData_StringQueryParam_BothLabelsReceiveSameValue [5 s]
>>>>> 5/21/2026 4:36:49 AM PassData_BackwardsNavigation_PassesDataToPreviousPage Start
>>>>> 5/21/2026 4:36:52 AM PassData_BackwardsNavigation_PassesDataToPreviousPage Stop
  Passed PassData_BackwardsNavigation_PassesDataToPreviousPage [2 s]
>>>>> 5/21/2026 4:36:52 AM PassData_MultipleStringParams_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:37:01 AM PassData_MultipleStringParams_ReceivedByIQueryAttributable Stop
  Passed PassData_MultipleStringParams_ReceivedByIQueryAttributable [9 s]
>>>>> 5/21/2026 4:37:01 AM PassData_IQueryAttributable_ReceivesDecodedValues Start
>>>>> 5/21/2026 4:37:07 AM PassData_IQueryAttributable_ReceivesDecodedValues Stop
  Passed PassData_IQueryAttributable_ReceivesDecodedValues [5 s]
>>>>> 5/21/2026 4:37:07 AM PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack Start
>>>>> 5/21/2026 4:37:17 AM PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack Stop
  Passed PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack [10 s]
>>>>> 5/21/2026 4:37:17 AM BackButtonBehavior_TextOverride_CustomTextShownOnBackButton Start
>>>>> 5/21/2026 4:37:26 AM BackButtonBehavior_TextOverride_CustomTextShownOnBackButton Stop
  Passed BackButtonBehavior_TextOverride_CustomTextShownOnBackButton [8 s]
>>>>> 5/21/2026 4:37:26 AM BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter Start
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter Stop
  Passed BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter [9 s]
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate Start
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate Stop
BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate: Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks Start
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks Stop
BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks: Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:37:36 AM BackButtonBehavior_IconOverride_CustomIconShownOnBackButton Start
  Skipped BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate [50 ms]
  Error Message:
   Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
  Standard Output Messages:
 Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771

  Skipped BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks [36 ms]
  Error Message:
   Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
  Standard Output Messages:
 Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771

>>>>> 5/21/2026 4:37:45 AM BackButtonBehavior_IconOverride_CustomIconShownOnBackButton Stop
  Passed BackButtonBehavior_IconOverride_CustomIconShownOnBackButton [9 s]
>>>>> 5/21/2026 4:37:45 AM PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams Start
>>>>> 5/21/2026 4:38:00 AM PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams Stop
>>>>> 5/21/2026 4:38:00 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
  Failed PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams [18 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
   at Microsoft.Maui.TestCases.Tests.ShellNavigationFeatureTests.PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs:line 855
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

>>>>> 5/21/2026 4:38:03 AM PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly Start
>>>>> 5/21/2026 4:38:18 AM PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly Stop
>>>>> 5/21/2026 4:38:18 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
  Failed PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly [18 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
   at Microsoft.Maui.TestCases.Tests.ShellNavigationFeatureTests.PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs:line 894
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

NUnit Adapter 4.5.0.0: Test execution complete

Test Run Failed.
Total tests: 54
     Passed: 50
     Failed: 2
    Skipped: 2
 Total time: 5.6584 Minutes

🟢 With fix — 🖥️ ShellNavigationFeatureTests: FAIL ❌ · 367s

(truncated to last 15,000 chars)

igationSucceeds Start
  Passed RouteRegistration_UnregisterRoute_NavigationFails [1 s]
>>>>> 5/21/2026 4:41:29 AM RouteRegistration_ReRegisterRoute_NavigationSucceeds Stop
  Passed RouteRegistration_ReRegisterRoute_NavigationSucceeds [4 s]
>>>>> 5/21/2026 4:41:29 AM CancelNavigation_NavigationIsBlocked_StaysOnMain Start
>>>>> 5/21/2026 4:41:37 AM CancelNavigation_NavigationIsBlocked_StaysOnMain Stop
  Passed CancelNavigation_NavigationIsBlocked_StaysOnMain [7 s]
>>>>> 5/21/2026 4:41:37 AM DeferralNavigation_NavigationCompletes_AfterDelay Start
>>>>> 5/21/2026 4:41:47 AM DeferralNavigation_NavigationCompletes_AfterDelay Stop
  Passed DeferralNavigation_NavigationCompletes_AfterDelay [10 s]
>>>>> 5/21/2026 4:41:47 AM TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo Start
>>>>> 5/21/2026 4:41:49 AM TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo Stop
  Passed TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo [2 s]
>>>>> 5/21/2026 4:41:49 AM TabStack_OnPushAsync_SubPage1_TabStackCountIsThree Start
>>>>> 5/21/2026 4:41:51 AM TabStack_OnPushAsync_SubPage1_TabStackCountIsThree Stop
  Passed TabStack_OnPushAsync_SubPage1_TabStackCountIsThree [1 s]
>>>>> 5/21/2026 4:41:51 AM TabStack_OnPushAsync_SubPage2_TabStackCountIsFour Start
>>>>> 5/21/2026 4:41:53 AM TabStack_OnPushAsync_SubPage2_TabStackCountIsFour Stop
  Passed TabStack_OnPushAsync_SubPage2_TabStackCountIsFour [1 s]
>>>>> 5/21/2026 4:41:53 AM TabStack_OnPopAsync_SubPage2_TabStackCountIsThree Start
>>>>> 5/21/2026 4:41:54 AM TabStack_OnPopAsync_SubPage2_TabStackCountIsThree Stop
  Passed TabStack_OnPopAsync_SubPage2_TabStackCountIsThree [1 s]
>>>>> 5/21/2026 4:41:54 AM TabStack_OnPopToRootAsync_ReturnsToMainPage Start
>>>>> 5/21/2026 4:41:56 AM TabStack_OnPopToRootAsync_ReturnsToMainPage Stop
  Passed TabStack_OnPopToRootAsync_ReturnsToMainPage [1 s]
>>>>> 5/21/2026 4:41:56 AM TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage Start
>>>>> 5/21/2026 4:41:59 AM TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage Stop
  Passed TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage [3 s]
>>>>> 5/21/2026 4:41:59 AM TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo Start
>>>>> 5/21/2026 4:42:01 AM TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo Stop
>>>>> 5/21/2026 4:42:01 AM TabStack_OnRemovePage_NoOp_WhenNothingToRemove Start
  Passed TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo [1 s]
>>>>> 5/21/2026 4:42:02 AM TabStack_OnRemovePage_NoOp_WhenNothingToRemove Stop
>>>>> 5/21/2026 4:42:02 AM TabStack_GetNavigationStack_TabStackMatchesNavigationStack Start
  Passed TabStack_OnRemovePage_NoOp_WhenNothingToRemove [1 s]
>>>>> 5/21/2026 4:42:08 AM TabStack_GetNavigationStack_TabStackMatchesNavigationStack Stop
  Passed TabStack_GetNavigationStack_TabStackMatchesNavigationStack [6 s]
>>>>> 5/21/2026 4:42:08 AM NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage Start
>>>>> 5/21/2026 4:42:13 AM NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage Stop
  Passed NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage [5 s]
>>>>> 5/21/2026 4:42:13 AM NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped Start
>>>>> 5/21/2026 4:42:14 AM NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped Stop
>>>>> 5/21/2026 4:42:14 AM NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage Start
  Passed NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped [807 ms]
>>>>> 5/21/2026 4:42:16 AM NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage Stop
>>>>> 5/21/2026 4:42:16 AM NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage Start
  Passed NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage [2 s]
>>>>> 5/21/2026 4:42:17 AM NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage Stop
>>>>> 5/21/2026 4:42:17 AM NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged Start
  Passed NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage [740 ms]
>>>>> 5/21/2026 4:42:23 AM NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged Stop
  Passed NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged [5 s]
>>>>> 5/21/2026 4:42:23 AM NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain Start
>>>>> 5/21/2026 4:42:23 AM NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain Stop
>>>>> 5/21/2026 4:42:23 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged Start
  Passed NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain [735 ms]
>>>>> 5/21/2026 4:42:24 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged Stop
>>>>> 5/21/2026 4:42:24 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged Start
>>>>> 5/21/2026 4:42:25 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged Stop
>>>>> 5/21/2026 4:42:25 AM NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged Start
  Passed NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged [1 s]
  Passed NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged [456 ms]
>>>>> 5/21/2026 4:42:30 AM NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged Stop
  Passed NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged [4 s]
>>>>> 5/21/2026 4:42:30 AM NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 Start
>>>>> 5/21/2026 4:42:31 AM NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 Stop
  Passed NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 [1 s]
>>>>> 5/21/2026 4:42:31 AM NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged Start
>>>>> 5/21/2026 4:42:37 AM NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged Stop
  Passed NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged [5 s]
>>>>> 5/21/2026 4:42:37 AM NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA Start
>>>>> 5/21/2026 4:42:38 AM NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA Stop
  Passed NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA [1 s]
>>>>> 5/21/2026 4:42:38 AM NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot Start
>>>>> 5/21/2026 4:42:43 AM NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot Stop
  Passed NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot [5 s]
>>>>> 5/21/2026 4:42:43 AM NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot Start
>>>>> 5/21/2026 4:42:44 AM NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot Stop
>>>>> 5/21/2026 4:42:44 AM PassData_StringQueryParam_ReceivedByIQueryAttributable Start
  Passed NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot [476 ms]
>>>>> 5/21/2026 4:42:52 AM PassData_StringQueryParam_ReceivedByIQueryAttributable Stop
  Passed PassData_StringQueryParam_ReceivedByIQueryAttributable [7 s]
>>>>> 5/21/2026 4:42:52 AM PassData_DictionaryParam_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:42:57 AM PassData_DictionaryParam_ReceivedByIQueryAttributable Stop
  Passed PassData_DictionaryParam_ReceivedByIQueryAttributable [5 s]
>>>>> 5/21/2026 4:42:57 AM PassData_SingleUseParams_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:43:03 AM PassData_SingleUseParams_ReceivedByIQueryAttributable Stop
  Passed PassData_SingleUseParams_ReceivedByIQueryAttributable [5 s]
>>>>> 5/21/2026 4:43:03 AM PassData_StringQueryParam_BothLabelsReceiveSameValue Start
>>>>> 5/21/2026 4:43:08 AM PassData_StringQueryParam_BothLabelsReceiveSameValue Stop
  Passed PassData_StringQueryParam_BothLabelsReceiveSameValue [5 s]
>>>>> 5/21/2026 4:43:08 AM PassData_BackwardsNavigation_PassesDataToPreviousPage Start
>>>>> 5/21/2026 4:43:11 AM PassData_BackwardsNavigation_PassesDataToPreviousPage Stop
  Passed PassData_BackwardsNavigation_PassesDataToPreviousPage [2 s]
>>>>> 5/21/2026 4:43:11 AM PassData_MultipleStringParams_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:43:21 AM PassData_MultipleStringParams_ReceivedByIQueryAttributable Stop
  Passed PassData_MultipleStringParams_ReceivedByIQueryAttributable [9 s]
>>>>> 5/21/2026 4:43:21 AM PassData_IQueryAttributable_ReceivesDecodedValues Start
>>>>> 5/21/2026 4:43:27 AM PassData_IQueryAttributable_ReceivesDecodedValues Stop
  Passed PassData_IQueryAttributable_ReceivesDecodedValues [5 s]
>>>>> 5/21/2026 4:43:27 AM PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack Start
>>>>> 5/21/2026 4:43:37 AM PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack Stop
  Passed PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack [10 s]
>>>>> 5/21/2026 4:43:37 AM BackButtonBehavior_TextOverride_CustomTextShownOnBackButton Start
>>>>> 5/21/2026 4:43:46 AM BackButtonBehavior_TextOverride_CustomTextShownOnBackButton Stop
  Passed BackButtonBehavior_TextOverride_CustomTextShownOnBackButton [9 s]
>>>>> 5/21/2026 4:43:46 AM BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter Start
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter Stop
  Passed BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter [9 s]
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate Start
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate Stop
BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate: Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks Start
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks Stop
BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks: Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IconOverride_CustomIconShownOnBackButton Start
  Skipped BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate [45 ms]
  Error Message:
   Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
  Standard Output Messages:
 Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771

  Skipped BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks [36 ms]
  Error Message:
   Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
  Standard Output Messages:
 Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771

>>>>> 5/21/2026 4:44:04 AM BackButtonBehavior_IconOverride_CustomIconShownOnBackButton Stop
  Passed BackButtonBehavior_IconOverride_CustomIconShownOnBackButton [8 s]
>>>>> 5/21/2026 4:44:04 AM PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams Start
>>>>> 5/21/2026 4:44:20 AM PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams Stop
>>>>> 5/21/2026 4:44:20 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
  Failed PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams [18 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
   at Microsoft.Maui.TestCases.Tests.ShellNavigationFeatureTests.PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs:line 855
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

>>>>> 5/21/2026 4:44:23 AM PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly Start
>>>>> 5/21/2026 4:44:38 AM PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly Stop
>>>>> 5/21/2026 4:44:38 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
  Failed PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly [18 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
   at Microsoft.Maui.TestCases.Tests.ShellNavigationFeatureTests.PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs:line 894
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

NUnit Adapter 4.5.0.0: Test execution complete

Test Run Failed.
Total tests: 54
     Passed: 50
     Failed: 2
    Skipped: 2
 Total time: 4.4491 Minutes

🔴 Without fix — 🧪 ShellParameterPassingTests: FAIL ✅ · 12s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/TestUtils/TestUtils.csproj (in 526 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 527 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 578 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 602 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj (in 1.3 sec).
  5 of 10 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0/Microsoft.Maui.Maps.dll
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0/Microsoft.Maui.Controls.Maps.dll
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0/Microsoft.Maui.Controls.Xaml.dll
  TestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/TestUtils/Debug/netstandard2.0/Microsoft.Maui.TestUtils.dll
  Controls.Core.UnitTests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.14]   Discovering: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.80]   Discovered:  Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.80]   Starting:    Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.92]     MultipleIntermediatePagesEachReceiveOwnPrefixedParams [FAIL]
[xUnit.net 00:00:00.92]       Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.92]       Stack Trace:
[xUnit.net 00:00:00.92]         /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(861,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.MultipleIntermediatePagesEachReceiveOwnPrefixedParams()
[xUnit.net 00:00:00.92]         --- End of stack trace from previous location ---
  Passed UrlParameter [51 ms]
  Passed InitialNavigationDoesntSetQueryAttributesProperty [23 ms]
  Passed ReNavigatingToCurrentLocationPassesParameters(useDataTemplates: True) [3 ms]
  Passed ReNavigatingToCurrentLocationPassesParameters(useDataTemplates: False) [< 1 ms]
  Passed NavigationWithQueryStringThenWithoutQueryString [2 ms]
  Passed NavigatingBackToShellContentRetainsQueryParameter [3 ms]
  Failed MultipleIntermediatePagesEachReceiveOwnPrefixedParams [3 ms]
  Error Message:
   Assert.Single() Failure: The collection was empty
  Stack Trace:
     at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.MultipleIntermediatePagesEachReceiveOwnPrefixedParams() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 861
--- End of stack trace from previous location ---
  Passed BasicShellParameterTest [4 ms]
  Passed PopNavigationTriggersApplyQueryAttributes [2 ms]
[xUnit.net 00:00:00.94]       Assert.Equal() Failure: Strings differ
[xUnit.net 00:00:00.94]       Expected: "hello"
[xUnit.net 00:00:00.94]       Actual:   null
[xUnit.net 00:00:00.94]       Stack Trace:
[xUnit.net 00:00:00.94]         /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(822,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesQueryPropertyAttributes()
[xUnit.net 00:00:00.94]         --- End of stack trace from previous location ---
  Passed ExtraParametersArentReAppliedWhenNavigatingBackToShellContent [2 ms]
  Passed DotDotNavigationPassesShellParameters [1 ms]
  Passed ExtraParametersDontGetRetained [3 ms]
[xUnit.net 00:00:00.94]     IntermediatePageReceivesQueryPropertyAttributes [FAIL]
  Passed DotDotNavigationPassesParameters [< 1 ms]
  Passed PassesUrlInShellParameter [< 1 ms]
  Passed ShellNavigationQueryParametersPassedInAsReadOnly [< 1 ms]
  Failed IntermediatePageReceivesQueryPropertyAttributes [1 ms]
  Error Message:
   Assert.Equal() Failure: Strings differ
Expected: "hello"
Actual:   null
  Stack Trace:
     at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesQueryPropertyAttributes() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 822
--- End of stack trace from previous location ---
[xUnit.net 00:00:00.95]     IntermediatePageDoesNotReceiveUnprefixedParams [FAIL]
  Passed NavigatingBackToTabSetsQueryAttributesProperty [1 ms]
  Passed UriEncodedStringDecodesCorrectly [< 1 ms]
[xUnit.net 00:00:00.95]       Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.95]       Stack Trace:
[xUnit.net 00:00:00.95]         /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(920,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageDoesNotReceiveUnprefixedParams()
[xUnit.net 00:00:00.95]         --- End of stack trace from previous location ---
[xUnit.net 00:00:00.95]       Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.95]     IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable [FAIL]
[xUnit.net 00:00:00.95]       Stack Trace:
[xUnit.net 00:00:00.95]         /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(796,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable()
[xUnit.net 00:00:00.95]         --- End of stack trace from previous location ---
  Passed BasicQueryStringTest [< 1 ms]
  Passed FlyoutItemNavigationSetsQueryAttributesProperty [< 1 ms]
  Passed NavigationBetweenShellContentsPassesQueryString [< 1 ms]
  Passed NavigationBetweenFlyoutItemWithPushedPageRetainsQueryString [< 1 ms]
  Failed IntermediatePageDoesNotReceiveUnprefixedParams [< 1 ms]
  Error Message:
   Assert.Single() Failure: The collection was empty
  Stack Trace:
     at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageDoesNotReceiveUnprefixedParams() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 920
--- End of stack trace from previous location ---
  Passed NavigationWithQueryStringAndNoDataTemplate [< 1 ms]
  Passed SingleUseQueryParametersReplaceQueryStringParams [< 1 ms]
  Failed IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable [< 1 ms]
  Error Message:
   Assert.Single() Failure: The collection was empty
  Stack Trace:
     at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 796
--- End of stack trace from previous location ---
  Passed UriDecodesQueryString [< 1 ms]
[xUnit.net 00:00:00.96]     OverlappingParamNamesDeliverCorrectValueToEachPage [FAIL]
[xUnit.net 00:00:00.96]       Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.96]       Stack Trace:
[xUnit.net 00:00:00.96]         /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(892,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.OverlappingParamNamesDeliverCorrectValueToEachPage()
[xUnit.net 00:00:00.96]         --- End of stack trace from previous location ---
[xUnit.net 00:00:00.96]     IntermediatePageReceivesParamsOnReNavigation [FAIL]
[xUnit.net 00:00:00.96]       Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.96]       Stack Trace:
[xUnit.net 00:00:00.96]         /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(972,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesParamsOnReNavigation()
[xUnit.net 00:00:00.96]         --- End of stack trace from previous location ---
  Passed ShellSectionChangedSetsQueryAttributesProperty [< 1 ms]
  Passed LastPageStillReceivesUnprefixedParamsWithIntermediatePages [< 1 ms]
  Passed NavigationWithQueryStringWhenPageMatchesBindingContext [< 1 ms]
  Passed SetParameterOfTypeThatsNotAString [4 ms]
  Failed OverlappingParamNamesDeliverCorrectValueToEachPage [< 1 ms]
  Error Message:
   Assert.Single() Failure: The collection was empty
  Stack Trace:
     at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.OverlappingParamNamesDeliverCorrectValueToEachPage() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 892
--- End of stack trace from previous location ---
  Failed IntermediatePageReceivesParamsOnReNavigation [< 1 ms]
  Error Message:
   Assert.Single() Failure: The collection was empty
  Stack Trace:
     at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesParamsOnReNavigation() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 972
--- End of stack trace from previous location ---
  Passed TabBarNavigationSetsQueryAttributesProperty [1 ms]
  Passed NavigatingBackDoesntClearParametersFromPreviousPage [5 ms]
  Passed NavigatingBackAbsolutelyClearsParametersFromPreviousPage [< 1 ms]
[xUnit.net 00:00:00.98]   Finished:    Microsoft.Maui.Controls.Core.UnitTests
  Passed NavigationBetweenFlyoutItemsRetainsQueryString [1 ms]
  Passed ValidateReadOnlyDictionary [1 ms]
  Passed NavigatingBackToShellContentAbsolutelyClearsQueryParameter [< 1 ms]
  Passed IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery [1 ms]
  Passed TabBarNavigationWithGoToAsyncSetsQueryAttributesProperty [< 1 ms]

Test Run Failed.
Total tests: 41
     Passed: 35
     Failed: 6
 Total time: 1.3326 Seconds

🟢 With fix — 🧪 ShellParameterPassingTests: PASS ✅ · 9s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 476 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 477 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 485 ms).
  7 of 10 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0/Microsoft.Maui.Controls.Xaml.dll
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0/Microsoft.Maui.Controls.Maps.dll
  TestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/TestUtils/Debug/netstandard2.0/Microsoft.Maui.TestUtils.dll
  Controls.Core.UnitTests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.11]   Discovering: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.74]   Discovered:  Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.75]   Starting:    Microsoft.Maui.Controls.Core.UnitTests
  Passed UrlParameter [51 ms]
  Passed InitialNavigationDoesntSetQueryAttributesProperty [19 ms]
  Passed ReNavigatingToCurrentLocationPassesParameters(useDataTemplates: True) [3 ms]
  Passed ReNavigatingToCurrentLocationPassesParameters(useDataTemplates: False) [< 1 ms]
  Passed NavigationWithQueryStringThenWithoutQueryString [2 ms]
  Passed NavigatingBackToShellContentRetainsQueryParameter [3 ms]
  Passed MultipleIntermediatePagesEachReceiveOwnPrefixedParams [3 ms]
  Passed BasicShellParameterTest [2 ms]
  Passed PopNavigationTriggersApplyQueryAttributes [2 ms]
  Passed ExtraParametersArentReAppliedWhenNavigatingBackToShellContent [2 ms]
  Passed DotDotNavigationPassesShellParameters [1 ms]
  Passed ExtraParametersDontGetRetained [3 ms]
  Passed DotDotNavigationPassesParameters [< 1 ms]
  Passed PassesUrlInShellParameter [< 1 ms]
  Passed ShellNavigationQueryParametersPassedInAsReadOnly [< 1 ms]
  Passed IntermediatePageReceivesQueryPropertyAttributes [< 1 ms]
  Passed NavigatingBackToTabSetsQueryAttributesProperty [1 ms]
  Passed UriEncodedStringDecodesCorrectly [< 1 ms]
  Passed BasicQueryStringTest [< 1 ms]
  Passed FlyoutItemNavigationSetsQueryAttributesProperty [1 ms]
  Passed NavigationBetweenShellContentsPassesQueryString [1 ms]
  Passed NavigationBetweenFlyoutItemWithPushedPageRetainsQueryString [1 ms]
  Passed IntermediatePageDoesNotReceiveUnprefixedParams [< 1 ms]
  Passed NavigationWithQueryStringAndNoDataTemplate [< 1 ms]
  Passed SingleUseQueryParametersReplaceQueryStringParams [< 1 ms]
  Passed IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable [1 ms]
  Passed UriDecodesQueryString [< 1 ms]
  Passed ShellSectionChangedSetsQueryAttributesProperty [1 ms]
  Passed LastPageStillReceivesUnprefixedParamsWithIntermediatePages [< 1 ms]
  Passed NavigationWithQueryStringWhenPageMatchesBindingContext [< 1 ms]
  Passed SetParameterOfTypeThatsNotAString [3 ms]
  Passed OverlappingParamNamesDeliverCorrectValueToEachPage [< 1 ms]
  Passed IntermediatePageReceivesParamsOnReNavigation [1 ms]
  Passed TabBarNavigationSetsQueryAttributesProperty [< 1 ms]
  Passed NavigatingBackDoesntClearParametersFromPreviousPage [1 ms]
  Passed NavigatingBackAbsolutelyClearsParametersFromPreviousPage [< 1 ms]
[xUnit.net 00:00:00.91]   Finished:    Microsoft.Maui.Controls.Core.UnitTests
  Passed NavigationBetweenFlyoutItemsRetainsQueryString [6 ms]
  Passed ValidateReadOnlyDictionary [1 ms]
  Passed NavigatingBackToShellContentAbsolutelyClearsQueryParameter [< 1 ms]
  Passed IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery [< 1 ms]
  Passed TabBarNavigationWithGoToAsyncSetsQueryAttributesProperty [< 1 ms]

Test Run Successful.
Total tests: 41
     Passed: 41
 Total time: 1.2384 Seconds

⚠️ Failure Details

  • ShellNavigationFeatureTests FAILED with fix (should pass)
    • Device tests: 2 of 52 failed
📁 Fix files reverted (1 files)
  • src/Controls/src/Core/Shell/ShellNavigationManager.cs

🧪 UI Tests — Shell

Detected UI test categories: Shell

🧪 UI Test Execution Results

⏭️ SKIPPED — 0 passed, 0 failed, 1 skipped (platform: ios)

Category Result Tests Duration Notes
Shell ⏭️ SKIPPED 0s Runner threw an exception

Failures here are informational only — they do not block the gate or affect try-fix candidate scoring.


🔍 Pre-Flight — Context & Validation

Pre-Flight Summary — PR #35432

Issue (#35107)

Shell.GoToAsync with multi-segment routes (e.g. "product/review?product.sku=X&stars=5") silently drops query parameters intended for intermediate pages. Only the last page receives params. Existing prefix-based scoping (product.skusku for the product page) is in place in ShellRouteParameters but never reaches the page.

PR Fix (Author: mattleibow)

File: src/Controls/src/Core/Shell/ShellNavigationManager.cs

Approach: In ApplyQueryAttributes, after the existing baseShellItem is ShellContent and isLastItem branches, add a third branch:

else if (element is Page)
{
    if (filteredQuery.Count == 0 && !element.IsSet(ShellContent.QueryAttributesProperty))
        return;
    var mergedData = MergeData(element, filteredQuery, isPopping);
    if (mergedData.Count > 0 || !isPopping)
        element.SetValue(ShellContent.QueryAttributesProperty, mergedData);
}

Root cause cited: intermediate Page objects are freshly created by ShellSection.GetOrCreateFromRoute and have Parent == null at the time ApplyQueryAttributes runs, so neither the baseShellItem is ShellContent nor isLastItem branch fires; the parameters are silently dropped. The fix piggybacks on the already-existing ShellContent.QueryAttributesProperty propertyChanged handler (OnQueryAttributesPropertyChanged) which already dispatches to IQueryAttributable, propagates BindingContext, and reflects [QueryProperty] attributes.

Tests added by PR

  • Unit tests (ShellParameterPassingTests.cs, +202 lines, 8 new tests): intermediate page via IQueryAttributable, via [QueryProperty], multi-intermediate, overlapping names, no-leak of unprefixed params, no-empty-apply, re-navigation.
  • UI tests (ShellNavigationFeatureTests.cs, 2 tests, order 148/149): PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams, PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly.
  • HostApp rewrite of ShellNavigationControlPage.xaml.cs (large reformat, +856/-799).

Gate Result (already run, do not re-run)

Test Without Fix With Fix
ShellNavigationFeatureTests (UI) FAIL (expected) FAIL ❌ — TimeoutException waiting for elements; output also references unrelated iOS 26 bug #34771
ShellParameterPassingTests (Unit) FAIL (expected) PASS

Interpretation: The unit tests prove the fix is logically correct. The UI tests fail in both states with the same error signature (Appium TimeoutException + iOS 26 issue #34771 — known pre-existing). The gate flags this as "regression in another test" but the UI failures are likely environment/iOS-26-related, NOT caused by the fix.

Call sites of ApplyQueryAttributes(navPage, …)

  • ShellSection.cs:418 — iterates navStack, calls per page, with isLast = i == globalRoutes.Count - 1. This is where intermediate pages get the call with isLast=false.
  • ShellSection.cs:517 — different path, with the actual ShellContent.

Key infrastructure used by the fix

ShellContent.cs:376 OnQueryAttributesPropertyChangedApplyQueryAttributes(content, query, oldQuery):

  • Dispatches to IQueryAttributable.ApplyQueryAttributes
  • Walks BindingContext if it differs from the page
  • Reflects [QueryProperty] attributes (gated by RuntimeFeature.IsQueryPropertyAttributeSupported)

Areas where an alternative fix could differ

  1. Fix at call site (ShellSection.cs:418/375) — apply attributes when the page is created, before insertion, so the call path doesn't depend on whether the page is wrapped.
  2. Reuse BaseShellItem.ApplyQueryAttributes-style dispatch — extract the ShellContent.ApplyQueryAttributes(content, query, oldQuery) static into a reusable helper and call it directly on the page rather than routing through the attached property's propertyChanged handler.
  3. Move the page-handling into the existing baseShellItem is ShellContent branch by lifting baseShellItem discovery — detect the page case earlier and merge into one path.
  4. Set Parent (or attach to ShellContent) before ApplyQueryAttributes — fix the underlying ordering issue rather than adding a side-channel.

🔧 Fix — Analysis & Comparison

Try-Fix Aggregate Summary — PR #35432

Context

  • Issue: Shell GoToAsync: no way to pass query parameters to intermediate pages in multi-segment navigation #35107Shell.GoToAsync("product/review?product.sku=X&stars=5") silently drops the sku=X parameter intended for the intermediate product page. Only the last page receives query parameters.
  • PR's fix: add an else if (element is Page) branch to ShellNavigationManager.ApplyQueryAttributes that sets ShellContent.QueryAttributesProperty (attached) directly on intermediate pages, leveraging the existing OnQueryAttributesPropertyChanged dispatch.
  • Gate result (already run, did not re-execute): unit tests pass with the fix; UI tests fail both with and without the fix due to unrelated iOS 26 issues (Appium TimeoutException + reference to [iOS 26] BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate test fails with TimeoutException #34771). The unit-test result confirms the fix is logically correct.
  • Validation method: for each candidate, I built Controls.Core.UnitTests and ran every test matching FullyQualifiedName~Shell (309 tests, including the PR's 8 new ones).

Candidates

# Approach Build Shell tests (309) Verdict
1 Fix at the call site (ShellSection.GetOrCreateFromRoute) instead of inside ApplyQueryAttributes. Leaves the shared dispatch method untouched. ✅ 309/309 Works. Smaller blast radius; PR's centralized approach probably more maintainable.
2 Collapse isLastItem + is Page branches into one unified element is Page branch. Pure refactor of PR's fix. ✅ 309/309 Works. Stylistic improvement only; matter of taste.
3a Expose ShellContent.ApplyQueryAttributesInternal and call it directly + still SetValue on attached property. ❌ 5 failures (double-dispatch — Assert.Single() Failure: collection contained 2 items) Found a foot-gun.
3b Same as 3a but only call the internal dispatcher (no SetValue). ✅ 309/309 Works. More invasive (ShellContent.cs API expanded); subtle semantic loss (attached property no longer holds the value after dispatch).

Comparison vs PR's fix

All three working candidates (1, 2, 3b) deliver identical behavior on all 309 unit tests, including the 8 new ones the PR introduced (Intermediate*, OverlappingParamNames*, LastPageStillReceivesUnprefixedParams*, MultipleIntermediatePagesEachReceiveOwnPrefixedParams, IntermediatePageReceivesParamsOnReNavigation, IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery).

None of the candidates is demonstrably better than the PR's fix. Findings:

  • PR's design is the most conservative, smallest, and least-error-prone choice. It piggybacks on existing machinery (the QueryAttributesProperty propertyChanged handler) and keeps API surface unchanged.
  • Candidate 1 is a viable alternative if a reviewer specifically wants ApplyQueryAttributes untouched. It's not better, just differently scoped.
  • Candidate 2 is a clean-up; might be applied on top of the PR's fix as a follow-up refactor. Not blocking.
  • Candidate 3 revealed a real risk: calling both the SetValue and the direct dispatcher causes double-fire of IQueryAttributable.ApplyQueryAttributes. This is a useful safety lesson but the candidate itself is less attractive than the PR.

UI Test Failures (separate from fix correctness)

The gate reported PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams and PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly failing on iOS in both the fix-applied and fix-reverted runs, with the same Appium System.TimeoutException signature plus references to unrelated iOS 26 bug #34771. This points to environment/UI-test-infrastructure issues, not a regression caused by the fix. Unit-test coverage validates the underlying logic.

Recommendation

Keep the PR's fix as-is. The exploration confirms:

  1. The bug analysis is correct.
  2. The chosen fix location (ApplyQueryAttributes third branch) is reasonable and unifies handling for the only call sites that produce orphan Page instances.
  3. No alternative dramatically simplifies or improves the fix.
  4. UI test failures appear unrelated and should be investigated separately (iOS 26 environment, not Shell logic).

Optional follow-up: candidate 2 (collapsing the isLastItem/is Page branches) is a small readability improvement worth considering as a separate housekeeping PR.

Detailed candidate write-ups

  • try-fix-1/content.md — call-site fix in ShellSection.GetOrCreateFromRoute
  • try-fix-2/content.md — branch-collapse refactor
  • try-fix-3/content.md — direct dispatcher invocation (including the double-dispatch bug discovered)

📋 Report — Final Recommendation

PR #35432 — Comparative Report

Issue

#35107Shell.GoToAsync with multi-segment routes (e.g., "product/review?product.sku=X&stars=5") silently drops query parameters intended for intermediate pages. Only the last page receives params. Prefix-based scoping already exists in ShellRouteParameters but never reaches intermediate pages whose Parent is null when ApplyQueryAttributes runs.

Candidates Evaluated

# Candidate Approach Build Shell unit tests (309) UI tests (iOS) Notes
1 pr Add else if (element is Page) branch in ShellNavigationManager.ApplyQueryAttributes that sets ShellContent.QueryAttributesProperty attached property, leveraging existing OnQueryAttributesPropertyChanged dispatch. ✅ 309/309 (incl. 8 new tests) ❌ env-only (iOS-26 #34771, fails identically without fix) The submitted PR fix.
2 pr-plus-reviewer Identical to pr — expert review found no actionable findings above info severity. ✅ 309/309 ❌ env-only No sandbox patch applied; inline-findings.json is empty.
3 try-fix-1 Fix at the page-creation call site (ShellSection.GetOrCreateFromRoute) instead of inside ApplyQueryAttributes. ✅ 309/309 not re-run (env-only) Smaller blast radius but needs duplication if a second call site ever creates orphan pages.
4 try-fix-2 Pure refactor: collapse the existing isLastItem branch and the new is Page branch into a single unified branch that selects query vs filteredQuery based on isLastItem. ✅ 309/309 not re-run (env-only) Stylistic improvement only; matter of taste. Tightens an asymmetric early-exit guard.
5 try-fix-3 Expose ShellContent.ApplyQueryAttributesInternal and call it directly from ShellNavigationManager, bypassing the attached-property roundtrip. ✅ 309/309 (after fix to attempt 1) not re-run (env-only) Initial attempt caused double-dispatch (IQueryAttributable.ApplyQueryAttributes fired twice) — fixed by removing the SetValue. Expands API surface and loses the persisted attached-property state. Uncovered a real foot-gun that the PR's design inherently avoids.

Gate Result Reminder

Test type Without fix With fix
ShellParameterPassingTests (unit) FAIL (expected) PASS
ShellNavigationFeatureTests (UI, iOS) FAIL FAIL (identical Appium TimeoutException + iOS-26 #34771 reference)

The UI test failures reproduce both with and without the PR fix and match a known unrelated iOS 26 Appium issue. Unit tests are the authoritative correctness signal. No candidate failed regression tests — all candidates that produced a working build passed 309/309 Shell unit tests.

Per-dimension Highlights from Expert Review (pr)

  • Handler/Navigation lifecycle: The new branch correctly routes through ShellContent.OnQueryAttributesPropertyChanged, which already handles IQueryAttributable, BindingContext propagation, and [QueryProperty] reflection. No duplication, no new dispatch path.
  • Edge-case asymmetry (isLastItem has no early-exit guard; the new Page branch does): Intentional. isLastItem uses unfiltered query (typically non-empty); the new Page branch uses prefix-filtered filteredQuery (typically empty for most intermediates on most navigations). The guard prevents spurious SetValue(empty) on every intermediate. The !IsSet(...) half preserves clear-on-re-nav semantics.
  • Silent fallthrough (ShellSection/ShellItem that isn't a Page still skipped): Pre-existing behavior. No regression introduced.
  • Style scope creep (shellContent?.ChildAdded +=): Unrelated to the bug fix but consistent with the symmetric -= form used in the disposable. Acceptable.
  • Threading / performance / public API / accessibility: No concerns.
  • Test coverage: 8 new unit tests cover all canonical scenarios (IQueryAttributable, [QueryProperty], multi-intermediate, prefix overlap, no-unprefixed-leak, no-empty-application, re-navigation).

Comparative Reasoning

All five candidates are functionally equivalent on every unit test. The differentiators are non-functional:

  • try-fix-1 moves the fix to the call site. It does not solve the second potentially-orphan call site (ShellSection.cs:418 re-navigation path) — that path happened to pass because of pre-existing logic, but a future caller that creates an orphan Page would not be covered. The PR's central location handles all current and future callers of ApplyQueryAttributes uniformly.
  • try-fix-2 is a cosmetic refactor — neither better nor worse, and slightly mutates the last-page branch's behavior in an edge case (skip vs write-empty) that is consumer-equivalent but a subtle change in side-effect on the attached property.
  • try-fix-3 is strictly worse: it expands ShellContent's internal surface, loses persisted attached-property state, and ships with a double-dispatch hazard that the PR's design structurally prevents.
  • pr-plus-reviewer added nothing — the expert reviewer found no findings above info severity. The candidate collapses to pr.

Winner

pr — the PR as submitted.

Rationale:

  1. Smallest correct diff to production code (one new else if branch in ShellNavigationManager.cs).
  2. Reuses existing dispatch infrastructure (OnQueryAttributesPropertyChanged) with zero duplication.
  3. Structurally avoids the double-dispatch hazard that try-fix-3 uncovered.
  4. Covers all current and future callers of ApplyQueryAttributes uniformly (unlike try-fix-1 which is bound to one call site).
  5. Passes all 309 Shell unit tests, including the 8 new tests that fail without the fix.
  6. Expert reviewer produced zero actionable findings above info severity → pr-plus-reviewer ≡ pr.

Optional non-blocking follow-up: candidate try-fix-2's branch-collapse is a small readability improvement that could land as a separate housekeeping PR if a maintainer values the symmetry. Not blocking.

Outputs

  • CustomAgentLogsTmp/PRState/35432/PRAgent/expert-pr-eval/content.md — full expert review write-up
  • CustomAgentLogsTmp/PRState/35432/PRAgent/inline-findings.json — empty findings array (no inline comments to post)
  • CustomAgentLogsTmp/PRState/35432/PRAgent/winner.json — winner manifest

@kubaflo kubaflo changed the base branch from main to inflight/current May 21, 2026 18:58
Keep both PR's intermediate page param tests and upstream's
ApplyQueryAttributesNotCalledOnInactivePageDuringBackNavigation test.
Accept upstream removal of iOS 26 skip guards in ShellNavigationFeatureTests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kubaflo kubaflo merged commit 8fa27ae into inflight/current May 21, 2026
2 of 11 checks passed
@kubaflo kubaflo deleted the mattleibow/fix-intermediate-page-params branch May 21, 2026 19:21
@github-actions github-actions Bot added this to the .NET 10.0 SR8 milestone May 21, 2026
PureWeen pushed a commit that referenced this pull request Jun 2, 2026
…hell navigation (#35432)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Description

Fixes #35107

When `Shell.GoToAsync` pushes multiple pages in a single call (e.g.,
`"product/review"`), only the **last page** receives query parameters.
All intermediate pages silently receive nothing — no
`IQueryAttributable.ApplyQueryAttributes` call, no `[QueryProperty]`
values set, no `BindingContext` propagation.

## Root Cause

`ShellNavigationManager.ApplyQueryAttributes` has two branches for
delivering parameters:

1. **`baseShellItem is ShellContent`** — applies params via the
ShellContent instance method
2. **`isLastItem`** — applies params by setting the
`QueryAttributesProperty` attached property

For intermediate pages (not last in the stack), the method tries to find
a `BaseShellItem` parent:

```csharp
if (!(element is BaseShellItem baseShellItem))
    baseShellItem = element?.Parent as BaseShellItem;
```

But intermediate pages were **just created** by
`ShellSection.GetOrCreateFromRoute` and have not been added to the
visual tree yet. Their `Parent` is `null`, so `baseShellItem` is `null`.
Since the page is not a `ShellContent` and is not the last item,
**neither branch runs** and the parameters are silently dropped.

## The Fix

Added a third branch after the existing two:

```csharp
else if (element is Page)
{
    var mergedData = MergeData(element, filteredQuery, isPopping);
    if (mergedData.Count > 0 || !isPopping)
    {
        element.SetValue(ShellContent.QueryAttributesProperty, mergedData);
    }
}
```

This sets the `QueryAttributesProperty` attached property directly on
the page. The existing property-changed handler
(`ShellContent.OnQueryAttributesPropertyChanged`) already handles:
- `IQueryAttributable` interface dispatch
- `BindingContext` propagation (if BindingContext differs from the page)
- `[QueryProperty]` attribute reflection
- `ShellNavigationQueryParameters` read-only wrapping

No logic was duplicated — the fix reuses the same infrastructure that
already works for the last page and ShellContent cases.

## How Parameter Scoping Works

Shell already has a prefix-based scoping mechanism for targeting
specific pages in a multi-page navigation. For a route like
`"product/review"`:

- **`?product.sku=seed-tomato`** → delivered to the page with route
`"product"` as `sku=seed-tomato`
- **`?stars=5`** → delivered to the last page (`"review"`) as `stars=5`
- **`?product.name=Widget&name=Alice`** → `"product"` gets
`name=Widget`, `"review"` gets `name=Alice` (no cross-contamination)

This prefix mechanism (`ShellRouteParameters` constructor with prefix
filtering) was already implemented and correct — it just could not
deliver because of the null-parent bug.

## Testing

**Unit tests** (`ShellParameterPassingTests.cs` — 6 new tests):
- Intermediate page receives prefixed params via `IQueryAttributable`
- Intermediate page receives prefixed params via `[QueryProperty]`
- Last page still receives unprefixed params (regression)
- Multiple intermediate pages each receive their own prefixed params
(3-page deep)
- Overlapping param names deliver correct distinct values to each page
- Intermediate page does NOT receive unprefixed params meant for the
last page

**UI tests** (`ShellNavigationFeatureTests.cs` — 2 new tests):
- Multi-page navigation delivers prefixed params to intermediate and
unprefixed to last; verifies intermediate does not leak unprefixed
params
- Overlapping `name` key scoped correctly — intermediate and detail each
see only their own value

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shell GoToAsync: no way to pass query parameters to intermediate pages in multi-segment navigation

7 participants